using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
using ICSharpCode.TextEditor.Document;

namespace ICSharpCode.TextEditor
{
    public class FoldMargin : AbstractMargin
    {
        private int selectedFoldLine = -1;

        private int foldMarkStyle = 0;

        private FoldingManager foldingManager = null;

        public override Size Size => new Size(textArea.TextView.FontHeight, -1);

        public override bool IsVisible => textArea.TextEditorProperties.EnableFolding;

        public FoldMargin(TextArea textArea)
            : base(textArea)
        {
            foldingManager = textArea.Document.FoldingManager;
        }

        public override void Paint(Graphics g, Rectangle rect)
        {
            if (rect.Width <= 0 || rect.Height <= 0)
            {
                return;
            }
            foldMarkStyle = base.TextEditorProperties.FoldMarkStyle;
            HighlightColor colorFor = textArea.Document.HighlightingStrategy.GetColorFor("LineNumbers");
            HighlightColor colorFor2 = textArea.Document.HighlightingStrategy.GetColorFor("FoldLine");
            Brush brush = (textArea.Enabled ? BrushRegistry.GetBrush(colorFor.BackgroundColor) : textArea.TextView.UnenableBackgroundBrush);
            if (!textArea.Enabled)
            {
                g.FillRectangle(brush, rect);
            }
            Pen foldLinePen = new Pen(colorFor2.Color);
            List<FoldLine> list = new List<FoldLine>();
            g.SmoothingMode = SmoothingMode.HighQuality;
            checked
            {
                for (int i = 0; i < unchecked(checked(base.DrawingPosition.Height + textArea.TextView.VisibleLineDrawingRemainder) / textArea.TextView.FontHeight) + 1; i++)
                {
                    Rectangle rectangle = new Rectangle(base.DrawingPosition.X, base.DrawingPosition.Top + i * textArea.TextView.FontHeight - textArea.TextView.VisibleLineDrawingRemainder, base.DrawingPosition.Width, textArea.TextView.FontHeight);
                    if (rect.IntersectsWith(rectangle))
                    {
                        bool isOpened = false;
                        bool isDrawFoldMark = false;
                        int firstLogicalLine = textArea.Document.GetFirstLogicalLine(textArea.TextView.FirstPhysicalLine + i);
                        if (firstLogicalLine < textArea.Document.TotalNumberOfLines)
                        {
                            PaintFoldMarker(g, firstLogicalLine, rectangle, out isDrawFoldMark, out isOpened);
                        }
                        if (unchecked(foldMarkStyle >= 3 && isDrawFoldMark))
                        {
                            PaintFoldLine(g, rectangle, rectangle.Bottom, foldLinePen, isOpened);
                            list.Add(new FoldLine(rectangle.Bottom, isOpened));
                        }
                    }
                }
                foldingManager.UpdateFoldingLines(list);
                g.SmoothingMode = SmoothingMode.Default;
            }
        }

        private bool SelectedFoldingFrom(List<FoldMarker> list)
        {
            if (list != null)
            {
                for (int i = 0; i < list.Count; i = checked(i + 1))
                {
                    if (selectedFoldLine == list[i].StartLine)
                    {
                        return true;
                    }
                }
            }
            return false;
        }

        private void PaintFoldLine(Graphics g, Rectangle rectangle, int position, Pen foldLinePen, bool isOpened)
        {
            if (!isOpened)
            {
                g.DrawLine(foldLinePen, new Point(checked(rectangle.X + 2), position), new Point(rectangle.Right, position));
            }
        }

        private void PaintFoldMarker(Graphics g, int lineNumber, Rectangle drawingRectangle, out bool isDrawFoldMark, out bool isOpened)
        {
            HighlightColor colorFor = textArea.Document.HighlightingStrategy.GetColorFor("FoldLine");
            HighlightColor colorFor2 = textArea.Document.HighlightingStrategy.GetColorFor("SelectedFoldLine");
            List<FoldMarker> foldingsWithStart = textArea.Document.FoldingManager.GetFoldingsWithStart(lineNumber);
            List<FoldMarker> foldingsContainsLineNumber = textArea.Document.FoldingManager.GetFoldingsContainsLineNumber(lineNumber);
            List<FoldMarker> foldingsWithEnd = textArea.Document.FoldingManager.GetFoldingsWithEnd(lineNumber);
            bool flag = foldingsWithStart.Count > 0;
            bool flag2 = foldingsContainsLineNumber.Count > 0;
            bool flag3 = foldingsWithEnd.Count > 0;
            bool flag4 = SelectedFoldingFrom(foldingsWithStart);
            bool flag5 = SelectedFoldingFrom(foldingsContainsLineNumber);
            bool flag6 = SelectedFoldingFrom(foldingsWithEnd);
            isOpened = true;
            isDrawFoldMark = false;
            checked
            {
                int num = (int)Math.Round((float)textArea.TextView.FontHeight * 0.57f);
                num -= unchecked(num % 2);
                int num2 = drawingRectangle.Y + unchecked(checked(drawingRectangle.Height - num) / 2);
                int num3 = drawingRectangle.X + unchecked(checked(drawingRectangle.Width - num) / 2) + unchecked(num / 2);
                if (flag)
                {
                    bool flag7 = true;
                    bool flag8 = false;
                    foreach (FoldMarker item in foldingsWithStart)
                    {
                        if (item.IsFolded)
                        {
                            flag7 = false;
                        }
                        flag8 = item.EndLine > item.StartLine;
                    }
                    bool flag9 = false;
                    foreach (FoldMarker item2 in foldingsWithEnd)
                    {
                        if (item2.EndLine > item2.StartLine && !item2.IsFolded)
                        {
                            flag9 = true;
                        }
                    }
                    DrawFoldMarker(g, new RectangleF(drawingRectangle.X + unchecked(checked(drawingRectangle.Width - num) / 2), num2, num, num), flag7, flag4 || unchecked(flag5 && flag2 && (flag9 || flag8)));
                    isOpened = flag7;
                    isDrawFoldMark = true;
                    if (foldMarkStyle < 3)
                    {
                        if (unchecked(flag2 || flag9))
                        {
                            g.DrawLine(BrushRegistry.GetPen(flag5 ? colorFor2.Color : colorFor.Color), num3, drawingRectangle.Top, num3, num2 - 1);
                        }
                        if (unchecked(flag2 || flag8))
                        {
                            g.DrawLine(BrushRegistry.GetPen(unchecked(flag6 || (flag4 && flag7) || flag5) ? colorFor2.Color : colorFor.Color), num3, num2 + num + 1, num3, drawingRectangle.Bottom);
                        }
                    }
                }
                else
                {
                    if (foldMarkStyle >= 3)
                    {
                        return;
                    }
                    if (flag3)
                    {
                        int num4 = drawingRectangle.Top + unchecked(drawingRectangle.Height / 2);
                        g.DrawLine(BrushRegistry.GetPen(unchecked(flag6 || flag4 || (flag5 && flag2)) ? colorFor2.Color : colorFor.Color), num3, num4, num3 + unchecked(num / 2), num4);
                        g.DrawLine(BrushRegistry.GetPen(unchecked(flag5 || flag6) ? colorFor2.Color : colorFor.Color), num3, drawingRectangle.Top, num3, num4);
                        if (flag2)
                        {
                            g.DrawLine(BrushRegistry.GetPen(flag5 ? colorFor2.Color : colorFor.Color), num3, num4 + 1, num3, drawingRectangle.Bottom);
                        }
                    }
                    else if (flag2)
                    {
                        g.DrawLine(BrushRegistry.GetPen(flag5 ? colorFor2.Color : colorFor.Color), num3, drawingRectangle.Top, num3, drawingRectangle.Bottom);
                    }
                }
            }
        }

        public override void HandleMouseMove(Point mousepos, MouseButtons mouseButtons)
        {
            bool enableFolding = textArea.Document.TextEditorProperties.EnableFolding;
            int lineNumber = checked(mousepos.Y + textArea.VirtualTop.Y) / textArea.TextView.FontHeight;
            int firstLogicalLine = textArea.Document.GetFirstLogicalLine(lineNumber);
            if (enableFolding && firstLogicalLine >= 0 && checked(firstLogicalLine + 1) < textArea.Document.TotalNumberOfLines)
            {
                List<FoldMarker> foldingsWithStart = textArea.Document.FoldingManager.GetFoldingsWithStart(firstLogicalLine);
                int num = selectedFoldLine;
                if (foldingsWithStart.Count > 0)
                {
                    selectedFoldLine = firstLogicalLine;
                }
                else
                {
                    selectedFoldLine = -1;
                }
                if (num != selectedFoldLine)
                {
                    textArea.Refresh(this);
                }
            }
        }

        public override void HandleMouseDown(Point mousepos, MouseButtons mouseButtons)
        {
            bool enableFolding = textArea.Document.TextEditorProperties.EnableFolding;
            int lineNumber = checked(mousepos.Y + textArea.VirtualTop.Y) / textArea.TextView.FontHeight;
            int firstLogicalLine = textArea.Document.GetFirstLogicalLine(lineNumber);
            if (!textArea.TextEditorProperties.EnableFolding || !textArea.MotherTextAreaControl.Enabled)
            {
                return;
            }
            textArea.Focus();
            if (!enableFolding || firstLogicalLine < 0 || checked(firstLogicalLine + 1) >= textArea.Document.TotalNumberOfLines)
            {
                return;
            }
            List<FoldMarker> foldingsWithStart = textArea.Document.FoldingManager.GetFoldingsWithStart(firstLogicalLine);
            foreach (FoldMarker item in foldingsWithStart)
            {
                item.IsFolded = !item.IsFolded;
            }
            textArea.Document.FoldingManager.NotifyFoldingsChanged(EventArgs.Empty);
        }

        public override void HandleMouseLeave(EventArgs e)
        {
            if (selectedFoldLine != -1)
            {
                selectedFoldLine = -1;
                textArea.Refresh(this);
            }
        }

        private void DrawFoldMarker(Graphics g, RectangleF rectangle, bool isOpened, bool isSelected)
        {
            HighlightColor colorFor = textArea.Document.HighlightingStrategy.GetColorFor("FoldMarker");
            HighlightColor colorFor2 = textArea.Document.HighlightingStrategy.GetColorFor("FoldLine");
            HighlightColor colorFor3 = textArea.Document.HighlightingStrategy.GetColorFor("SelectedFoldLine");
            checked
            {
                Rectangle rect = new Rectangle((int)rectangle.X, (int)rectangle.Y, (int)rectangle.Width, (int)rectangle.Height);
                if (foldMarkStyle == 0)
                {
                    g.DrawRectangle(BrushRegistry.GetPen(isSelected ? colorFor3.Color : colorFor2.Color), rect);
                    int num = (int)Math.Round((double)rectangle.Height / 8.0) + 1;
                    int num2 = unchecked(rect.Height / 2) + unchecked(rect.Height % 2);
                    g.DrawLine(BrushRegistry.GetPen(isSelected ? colorFor3.Color : colorFor.Color), rectangle.X + (float)num, rectangle.Y + (float)num2, rectangle.X + rectangle.Width - (float)num, rectangle.Y + (float)num2);
                    if (!isOpened)
                    {
                        g.DrawLine(BrushRegistry.GetPen(isSelected ? colorFor3.Color : colorFor.Color), rectangle.X + (float)num2, rectangle.Y + (float)num, rectangle.X + (float)num2, rectangle.Y + rectangle.Height - (float)num);
                    }
                    return;
                }
                if (foldMarkStyle == 1)
                {
                    Pen pen = BrushRegistry.GetPen(isSelected ? colorFor3.Color : colorFor.Color);
                    g.DrawLine(pen, new PointF(rectangle.X + rectangle.Width * 1f / 4f, rectangle.Y + rectangle.Height / 2f), new PointF(rectangle.X + rectangle.Width * 3f / 4f, rectangle.Y + rectangle.Height / 2f));
                    GraphicsPath graphicsPath = new GraphicsPath();
                    if (!isOpened)
                    {
                        g.DrawLine(pen, new PointF(rectangle.X + rectangle.Width / 2f, rectangle.Y + rectangle.Height * 1f / 4f), new PointF(rectangle.X + rectangle.Width / 2f, rectangle.Y + rectangle.Height * 3f / 4f));
                        graphicsPath.AddLines(new PointF[5]
                        {
                            new PointF(rectangle.X, rectangle.Y),
                            new PointF(rectangle.X + rectangle.Width * 3f / 4f, rectangle.Y),
                            new PointF(rectangle.Right, rectangle.Y + rectangle.Height / 2f),
                            new PointF(rectangle.X + rectangle.Width * 3f / 4f, rectangle.Bottom),
                            new PointF(rectangle.X, rectangle.Bottom)
                        });
                    }
                    else
                    {
                        graphicsPath.AddLines(new PointF[5]
                        {
                            new PointF(rectangle.X, rectangle.Y),
                            new PointF(rectangle.Right, rectangle.Y),
                            new PointF(rectangle.Right, rectangle.Y + rectangle.Height * 3f / 4f),
                            new PointF(rectangle.X + rectangle.Width / 2f, rectangle.Bottom),
                            new PointF(rectangle.X, rectangle.Y + rectangle.Height * 3f / 4f)
                        });
                    }
                    graphicsPath.CloseFigure();
                    g.DrawPath(pen, graphicsPath);
                    graphicsPath.Dispose();
                    return;
                }
                if (foldMarkStyle == 2)
                {
                    g.DrawEllipse(BrushRegistry.GetPen(isSelected ? colorFor3.Color : colorFor2.Color), rect);
                    int num3 = (int)Math.Round((double)rectangle.Height / 8.0) + 1;
                    int num4 = unchecked(rect.Height / 2) + unchecked(rect.Height % 2);
                    g.DrawLine(BrushRegistry.GetPen(isSelected ? colorFor3.Color : colorFor.Color), rectangle.X + (float)num3, rectangle.Y + (float)num4, rectangle.X + rectangle.Width - (float)num3, rectangle.Y + (float)num4);
                    if (!isOpened)
                    {
                        g.DrawLine(BrushRegistry.GetPen(isSelected ? colorFor3.Color : colorFor.Color), rectangle.X + (float)num4, rectangle.Y + (float)num3, rectangle.X + (float)num4, rectangle.Y + rectangle.Height - (float)num3);
                    }
                    return;
                }
                if (foldMarkStyle == 3)
                {
                    RectangleF rectangleF = new RectangleF(rectangle.X + 1f, rectangle.Y + 1f, rectangle.Width - 2f, rectangle.Height - 2f);
                    Brush brush = BrushRegistry.GetBrush(isSelected ? colorFor3.Color : colorFor.Color);
                    using (GraphicsPath graphicsPath2 = new GraphicsPath())
                    {
                        if (!isOpened)
                        {
                            graphicsPath2.AddLines(new PointF[3]
                            {
                                new PointF(rectangleF.X, rectangleF.Y),
                                new PointF(rectangleF.X + rectangleF.Width - 2f, rectangleF.Y + rectangleF.Height / 2f),
                                new PointF(rectangleF.X, rectangleF.Bottom)
                            });
                        }
                        else
                        {
                            graphicsPath2.AddLines(new PointF[3]
                            {
                                new PointF(rectangleF.X, rectangleF.Y),
                                new PointF(rectangleF.X + rectangleF.Width, rectangleF.Y),
                                new PointF(rectangleF.X + rectangleF.Width / 2f, rectangleF.Bottom - 2f)
                            });
                        }
                        graphicsPath2.CloseFigure();
                        g.FillPath(brush, graphicsPath2);
                        return;
                    }
                }
                if (foldMarkStyle == 4)
                {
                    int num5 = (int)Math.Round((double)rectangle.Height / 8.0) + 1;
                    int num6 = unchecked(rect.Height / 2) + unchecked(rect.Height % 2);
                    g.DrawLine(BrushRegistry.GetPen(isSelected ? colorFor3.Color : colorFor.Color), rectangle.X + (float)num5, rectangle.Y + (float)num6, rectangle.X + rectangle.Width - (float)num5, rectangle.Y + (float)num6);
                    if (!isOpened)
                    {
                        g.DrawLine(BrushRegistry.GetPen(isSelected ? colorFor3.Color : colorFor.Color), rectangle.X + (float)num6, rectangle.Y + (float)num5, rectangle.X + (float)num6, rectangle.Y + rectangle.Height - (float)num5);
                    }
                }
            }
        }
    }
}
